package com.yneusoft.manage.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.yneusoft.common.model.ResponseWrapper;
import com.yneusoft.dao.entity.User;
import com.yneusoft.dao.entity.UserState;
import com.yneusoft.dao.mapper.UserMapper;
import com.yneusoft.dao.mapper.UserStateMapper;
import com.yneusoft.manage.mapper.UserManageMapper;
import com.yneusoft.manage.model.*;
import com.yneusoft.manage.model.param.*;
import com.yneusoft.manage.model.result.CheckPhoneResult;
import com.yneusoft.manage.model.result.GetUserInfoResult;
import com.yneusoft.manage.model.result.GetUserListResult;
import com.yneusoft.manage.model.result.UploadResult;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsOperations;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author: wjw
 * @date: 2021/10/20 15:10
 * @description:
 */
@Service
@Transactional
public class UserManageService {

    @Autowired
    private UserMapper userMapper;

    private final GridFsOperations gridFsOperations;

    public UserManageService(GridFsOperations gridFsOperations) {
        this.gridFsOperations = gridFsOperations;
    }

    /**
     * 1.获取用户状态列表
     * @author: fzg
     * @return id 用户状态id; name 用户状态名称
     */
    public ResponseWrapper getUserStateList() {
        List<UserState> userStateList = UserState.dataList;
        List<UserStateListItemModel> result = JSONArray.parseArray(JSON.toJSONString(userStateList)).toJavaList(UserStateListItemModel.class);
        if (result != null){
            return ResponseWrapper.markSuccess(result);
        }else {
            return ResponseWrapper.markError();
        }
    }

    /**
     * 2.获取用户列表
     * @author: fzg
     * @param param 类
     * @return rowNumber 查出来的总记录数
     *         list      用户列表
     */
    public ResponseWrapper getUserList(SearchUserParam param){
        try{
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.like(StringUtils.isNotBlank(param.getSearchKey()), User::getName, param.getSearchKey())
                    .eq( param.getStateId()!= null, User::getStateId, param.getStateId())
                    .orderByDesc(User::getStateId)
                    .orderByDesc(User::getAid);
            //分页查询
            Page<User> userPage = userMapper.selectPage(new Page<>(param.getPage(), param.getPageSize()), wrapper);
            List<User> userList = userPage.getRecords();
            List<UserListItemModel> resultList = JSONArray.parseArray(JSON.toJSONString(userList)).toJavaList(UserListItemModel.class);
            //设置附件名称
            for(UserListItemModel user :resultList){
                //如果存在附件id，则查询并添加附件名称
                if(user.getEnclosureId()!= null){
                    GridFSFile gridFsFile = gridFsOperations.findOne(Query.query(Criteria.where("_id").is(user.getEnclosureId())));
                    String enclosureName = new String(gridFsFile.getFilename().getBytes(), StandardCharsets.ISO_8859_1);
                    user.setEnclosureName(enclosureName);
                }
            }
            GetUserListResult result = new GetUserListResult();
            result.setRowNumber((int)userPage.getTotal());
            result.setList(resultList);
            return ResponseWrapper.markSuccess(result);
        }
        catch (Exception e){
            e.printStackTrace();
            return ResponseWrapper.markError();
        }
    }

    /**
     * 3.删除用户
     * @author: fzg
     * @param param DeleteUserParam
     */
    @Transactional
    public ResponseWrapper delUser(DeleteUserParam param){
        try{
            User user = userMapper.selectById(param.getAid());
            String enclosureId = user.getEnclosureId();
            int result = userMapper.deleteById(param.getAid());
            if (result > 0){
                //如果用户存在附件则在删除用户后删除该附件
                if(enclosureId!=null){
                    gridFsOperations.delete(Query.query(Criteria.where("_id").is(enclosureId)));
                }
                return ResponseWrapper.markSuccess();
            }else {
                return ResponseWrapper.markError();
            }
        }
        catch (Exception e) {
            return ResponseWrapper.markError();
        }

    }

    /**
     * 4.更改用户状态
     * @author: fzg
     * @param param ChangeUserStateParam
     */
    @Transactional
    public ResponseWrapper changeUserState(ChangeUserStateParam param){
        //在切面中，更改了参数里的用户状态id和Name
        LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(User::getAid,param.getAid())
                .set(User::getStateId,param.getStateId())
                .set(User::getStateName,param.getStateName());
        int result = userMapper.update(null,wrapper);
        if (result > 0){
            return ResponseWrapper.markSuccess();
        }else {
            return ResponseWrapper.markError();
        }
    }

    /**
     * 5.【新增/修改】获取修改用户信息
     * @author: fzg
     * @param aid 用户aid
     * @return  name 用户名
     *          phone 手机号
     *          password 密码
     */
    public ResponseWrapper userInfo(Integer aid){
        User resultUser = userMapper.selectById(aid);
        GetUserInfoResult result = JSON.parseObject(JSON.toJSONString(resultUser), GetUserInfoResult.class);
        //存在附件则查询附件名称
        if(resultUser.getEnclosureId()!=null){
            GridFSFile gridFsFile = gridFsOperations.findOne(Query.query(Criteria.where("_id").is(resultUser.getEnclosureId())));
            String enclosureName = new String(gridFsFile.getFilename().getBytes(), StandardCharsets.ISO_8859_1);
            result.setEnclosureName(enclosureName);
        }
        if (result != null){
            return ResponseWrapper.markSuccess(result);
        }else {
            return ResponseWrapper.markError();
        }
    }

    /**
     * 6.【新增/修改】校验手机号是否存在
     * @author: fzg
     * @param param CheckPhoneParam类
     * @return  isExists 是否已存在【false：不存在，true：已存在】
     *          userInfo: name,phone,password
     */
    public ResponseWrapper checkPhone(CheckPhoneParam param){
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        //aid为-1是新增查询，其余为修改查询
        if (param.getAid()==-1){
            wrapper.eq(User::getPhone,param.getPhone());
        }else {
            wrapper.eq(User::getPhone,param.getPhone())
                    .ne(User::getAid,param.getAid());
        }
        User user = userMapper.selectOne(wrapper);
        CheckPhoneResult checkPoneResult = new CheckPhoneResult();
        //是否查询到用户
        if (user != null){
            GetUserInfoResult userObj = JSONArray.parseObject(JSON.toJSONString(user), GetUserInfoResult.class);
            //存在附件就设置附件名称
            if (userObj.getEnclosureId()!=null){
                GridFSFile gridFsFile = gridFsOperations.findOne(Query.query(Criteria.where("_id").is(userObj.getEnclosureId())));
                String enclosureName = new String(gridFsFile.getFilename().getBytes(), StandardCharsets.ISO_8859_1);
                userObj.setEnclosureName(enclosureName);
            }
            checkPoneResult.setIsExists(true);
            checkPoneResult.setUserInfo(userObj);
            return ResponseWrapper.markSuccess(checkPoneResult);
        }else {
            checkPoneResult.setIsExists(false);
            checkPoneResult.setUserInfo(null);
            return ResponseWrapper.markSuccess(checkPoneResult);
        }
    }

    /**
     * 7.【新增/修改】新增/修改用户信息（保存）
     * @author: fzg
     * @param param 参数类
     */
    @Transactional
    public ResponseWrapper saveUser(SaveUserParam param){
        User user = new User();
        user.setName(param.getName());
        user.setPhone(param.getPhone());
        user.setPassword(param.getPassword());
        user.setStateId(param.getStateId());
        user.setStateName(param.getStateName());
        if(param.getEnclosureId() != null){
            user.setEnclosureId(param.getEnclosureId());
        }
        System.out.println("service param  "+param);
        if (param.getAid() == null || param.getAid() <= 0){
            int result = userMapper.insert(user);
            if (result > 0){
                return ResponseWrapper.markCustomSuccess("新增成功！");
            }else {
                return ResponseWrapper.markCustomError("新增失败！");
            }
        }else {
            user.setAid(param.getAid());
            int r = userMapper.updateById(user);
            if (r > 0){
                return ResponseWrapper.markCustomSuccess("修改成功！");
            }else {
                return ResponseWrapper.markCustomError("修改失败！");
            }
        }
    }


    /**
     * 8.文件上传
     *
     * @param file 文件
     * @return 附件id
     */
    public ResponseWrapper uploadFile(MultipartFile file) {
        try (InputStream inputStream = file.getInputStream()) {
            //上传文件返回文件ID
            ObjectId objectId = gridFsOperations.store(inputStream, file.getOriginalFilename(), file.getContentType());
            UploadResult result = new UploadResult();
            result.setEnclosureId(objectId.toString());
            return ResponseWrapper.markSuccess(result);
        } catch (IOException ioException) {
            ioException.printStackTrace();
            return ResponseWrapper.markCustomError("上传失败");
        }

    }

    /**
     * 10.下载文件
     *
     * @param param EnclosureId 文件ID
     */
    public Map<String, Object> downloadFile(HttpServletResponse response, DownloadFileParam param) {
        //根据文件ID查询出文件
        Map<String, Object> map = new HashMap<>(2);
        String objectId = param.getEnclosureId();
        GridFSFile gridFsFile = gridFsOperations.findOne(Query.query(Criteria.where("_id").is(objectId)));
        if (gridFsFile != null) {
            GridFsResource gridFsResource = gridFsOperations.getResource(gridFsFile);
            //设置响应对象的响应内容的类型
            response.setCharacterEncoding("UTF-8");
            response.setContentType(gridFsResource.getContentType());
            response.setHeader("content-disposition", "attachment;filename=" + new String(gridFsFile.getFilename().getBytes(), StandardCharsets.ISO_8859_1));
            try (OutputStream outputStream = response.getOutputStream();
                 InputStream inputStream = gridFsResource.getInputStream()) {
                //读取inputStream中的所有字节并写入输出流中
                outputStream.write(inputStream.readAllBytes());
                map.put("code", 10000);
                map.put("message", "下载成功");
            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        } else {
            map.put("code", 99999);
            map.put("message", "文件不存在");
        }
        return map;
    }

    /**
     * 9.删除文件
     *
     * @param param 文件ID
     */
    @Transactional
    public ResponseWrapper deleteFile(DeleteFileParam param) {
        String objectId = param.getEnclosureId();
        try {
            gridFsOperations.delete(Query.query(Criteria.where("_id").is(objectId)));
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getEnclosureId,objectId);
            User user = userMapper.selectOne(wrapper);
            if(user != null){
                LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.set(User::getEnclosureId,null)
                        .eq(User::getAid,user.getAid());
                userMapper.update(null,updateWrapper);
            }
            return ResponseWrapper.markSuccess();
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseWrapper.markCustomError("删除失败");
        }
    }

}
